﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using UnitLibrary.Managers;
using UnitLibrary.GameObjects.UnitReaders;
using FarseerGames.FarseerPhysics.Collisions;

namespace UnitLibrary.GameObjects.Units
{
    /// <summary>
    /// Enum do describe the different types of towers in the game
    /// </summary>
    public enum TowerType
    {
        Tracking,
        Random,
        Spiral,
        SetDirection,
        Cross,
        RotatingCross
    }
    
    public class Tower : UnitGen
    {
        /// <summary>
        /// 
        /// </summary>
        public Tower()
        {
           
        }
        private double _shotTimer = 0;
        private double _shotTimerInterval = 500;
        private string _shotName;
        private bool _shotEnabled = false;
        private double _lifeTimer = 0;
        private double _lifeTimerInterval = 10000;
        private string _bulletName = "Default";
        private TowerM _towerManager;
        private TowerType _towerType = TowerType.Random;
        private Vector2 _shotDirection = Vector2.Zero;
        private double _shotSpacing = .75;
        private double _shotOffset = 0;
        private int direction = 0;
        private int directionOffset = 10;

        public double DegreesToRadian(double degrees)
        {
            return degrees / 57.2957795;
        }

        public double RadianToDegrees(double radian)
        {
            return 57.2957795 * radian;
        }

        public string BulletName
        {
            get { return _bulletName; }
            set
            {
                _bulletName = value;
                if (_components != null)
                    _shotTimerInterval = _components.bulletManager2.GetDefinition(_bulletName).AttackRate;
                else
                    _shotTimerInterval = 500;
            }
        }

        public double LifeTimerInterval
        {
            get { return _lifeTimerInterval; }
            set
            {
                _lifeTimerInterval = value;
                _lifeTimer = 0;
            }
        }

        public TowerType towerType
        {
            get { return _towerType; }
            set { _towerType = value; }
        }

        /// <summary>
        /// 
        /// </summary>
        public double ShotSpacing
        {
            get { return _shotSpacing; }
            set
            {
                _shotSpacing = value;
            }
        }

        public bool SensorCollision(Geom geom1, Geom geom2, ContactList contactlist)
        {
            Iid g1tag = (Iid)geom1.Tag;
            Iid g2tag = (Iid)geom2.Tag;
            //Geom 2 tag was never created, we don't know the type, so just return true

            if (geom1.Tag == null)
            {
                Console.WriteLine("Geom 1 tag inside of Tower.cs OnCollision was never instantiated");
                //Return true since we don't know what the geoms are
                return true;
            }
            if (geom2.Tag == null)
            {
                Console.WriteLine("Geom 2 tag inside of Tower.cs OnCollision was never instantiated");
                //Return true since we don't know what the geoms are
                return true;
            }
            if (g1tag.UnitID == UnitID.Tower)
            {
                switch (g2tag.UnitID)
                {
                    case UnitID.Enemy:
                        if(_shotEnabled)
                          TakeDamage(g2tag);
                          return true;
                    case UnitID.Tower:
                          return true;
                    default:
                          return true;
                }
            }
            return true;
        }

        private void TakeDamage(Iid g2tag)
        {
            this.Health -= _components.GetDamage(g2tag);
            if (this.Health < 0)
                _components.RemoveUnit(this.ID, true);
        }
        private void Shoot(Vector2 direction)
        {
            _components.CreateUnit(UnitID.Bullet, _bulletName, base.Position, direction);
            _shotTimer = 0;
            _shotEnabled = false;
        }

        private void ShootLogic()
        {
            switch (_towerType)
            {
                case TowerType.SetDirection:
                    break;
                case TowerType.Random:
                        _shotDirection.X = Utility.Util.random.Next(-10, 10);
                        _shotDirection.Y = Utility.Util.random.Next(-10, 10);
                        _shotDirection.Normalize();
                        Shoot(_shotDirection);
                    break;
                case TowerType.Spiral:
                    _shotOffset += _shotSpacing;
                    _shotDirection.X = (float)Math.Cos(_shotOffset);
                    _shotDirection.Y = (float)Math.Sin(_shotOffset);
                    Shoot(_shotDirection);
                    break;
                case TowerType.Cross:
                    direction = 0;
                    for( int i = 0; i < 4; i++)
                    {
                        _shotDirection.X = (float)Math.Cos(DegreesToRadian((double)direction));
                        _shotDirection.Y = (float)Math.Sin(DegreesToRadian((double)direction));
                        Shoot(_shotDirection);
                        direction += 90;
                    }
                    break;
                case TowerType.RotatingCross:
                    direction += directionOffset;
                    for (int i = 0; i < 4; i++)
                    {
                        _shotDirection.X = (float)Math.Cos(DegreesToRadian((double)direction));
                        _shotDirection.Y = (float)Math.Sin(DegreesToRadian((double)direction));
                        Shoot(_shotDirection);
                        direction += 90;
                    }                    
                    break;
                case TowerType.Tracking:
                    break;
            }
        }

        public override void Create(object genericUnit, ComponentM components, Vector2 location, Vector2 direction, bool addtophysics)
        { 
            base.Create(genericUnit, components, location, direction, addtophysics);
            if (_towerManager == null)
                _towerManager = components.towerManager;
            if (_geom.OnCollision == null)
                _geom.OnCollision += SensorCollision;
            Tower tower = (Tower)genericUnit;
            //Load bullet definition for this tower
            this._bulletName = tower._bulletName;
            _shotTimerInterval = components.bulletManager2.GetDefinition(_bulletName).AttackRate;
            this._lifeTimerInterval = tower._lifeTimerInterval;
            this._lifeTimer = 0;
            this._towerType = tower._towerType;
            this.ShotSpacing = tower._shotSpacing;
            this._shotDirection = Vector2.One;
            this._shotOffset = 0;
            this.direction = 0;
            this.directionOffset = 10;
            //Copy values
           
        }

        public override void Update(GameTime gametime)
        {
            _shotTimer += gametime.ElapsedGameTime.TotalMilliseconds;
            if (_shotTimer > _shotTimerInterval && !_shotEnabled)
            //Throw event that the tower is ready to shoot
            {
                _shotEnabled = true;
                ShootLogic();
            }

            _lifeTimer += gametime.ElapsedGameTime.TotalMilliseconds;
            if (_lifeTimer > _lifeTimerInterval)
            {
                _components.RemoveUnit(this.ID, false);
            }
            base.Update(gametime);
        }        
    }
}
